package com.example.demo.scheduledtask;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.example.demo.common.Constant;
import com.example.demo.config.ErpConfig;
import com.example.demo.mapper.PoMpsinfoMapper;
import com.example.demo.mapper.WmsPurchaseMapper;
import com.example.demo.mapper.WmsPurchaseNewMapper;
import com.example.demo.utils.SoapXmlUtil;
import com.example.demo.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * @author : Zhang.yt
 * @date : 2024/7/29
 */
@Component
@Slf4j
@DS("wms")
public class PurchaseGet {
    @Resource
    private WmsPurchaseNewMapper wmsPurchaseNewMapper;

    @Autowired
    private SoapXmlUtil soapXmlUtil;

    @Autowired
    private PoMpsinfoMapper poMpsinfoMapper;

    @Resource
    private ErpConfig erpConfig;

    @Resource
    private WmsPurchaseMapper wmsPurchaseMapper;


    /**
     * 采购收货回调
     */
    @Scheduled(fixedDelay = 7 * 1000)//开启定时同步
    //@Async(value = "taskExecutor")
    public void purchaseGet() {
        //查询收货单主表
        PurchaseNotReceiptVo purchaseNotReceiptVo = wmsPurchaseNewMapper.getPurchaseGetNew();

        if (ObjectUtils.isEmpty(purchaseNotReceiptVo) || ObjectUtils.isEmpty(purchaseNotReceiptVo.getPmds055())) {
            //无正常单据需要处理时，将回填超时得单据再重传下(注意，超时得提示信息需要固定，不能修改)
            log.info("未查询到采购收货回调数据，修改报错数据重新过账");
            wmsPurchaseMapper.purchaseGetLose();
            return;
        }

        try {
            //超过20秒未获取到锁就退出
//            if (!lock.tryLock(60, TimeUnit.SECONDS)) {
//                return;
//            }
            purchaseNotReceiptVo.setPmdssite(Constant.PMDSSITE_AMA);
            purchaseNotReceiptVo.setActionType(Constant.ActionType_I);
            //查询收货单细表
            List<PurchaseNotReceiptListVo> purchaseGetListNew = wmsPurchaseNewMapper.getPurchaseGetListNew(purchaseNotReceiptVo.getPmds055());
            if (CollUtil.isEmpty(purchaseGetListNew)) {
                log.info("收货单号:{}细表无数据", purchaseNotReceiptVo.getPmds055());
                wmsPurchaseNewMapper.updateStSlOpflg(purchaseNotReceiptVo.getPmds055(), 2, "细表无数据该单未回写！");
                return;
            }

            //根据采购收货明细获取是采购单号
            Set<String> purchaseOrderNos = purchaseGetListNew.stream().map(PurchaseNotReceiptListVo::getPmdt001).collect(Collectors.toSet());
            //查询采购单采购详情
            if (CollUtil.isEmpty(purchaseOrderNos)) {
                log.info("未获取到采购单信息");
                wmsPurchaseNewMapper.updateStSlOpflg(purchaseNotReceiptVo.getPmds055(), 2, "未获取到采购单信息");
                return;
            }
            //每次都重新拉取下erp采购单，避免ERP修改了和本地不同步
            for (String purchaseOrderNo : purchaseOrderNos) {
                poMpsinfoMapper.syncProcurementDetailsByOrderNo(purchaseOrderNo);
                //更新委外采购可回写项次数据
                poMpsinfoMapper.wmsErpProcurementDetailsPmdnseq(purchaseOrderNo);
            }
            Integer Pmdl005 = wmsPurchaseNewMapper.getPmdl005(purchaseOrderNos);
            if (ObjectUtil.isEmpty(Pmdl005)) {
                log.info("未获取到采购单信息");
                wmsPurchaseNewMapper.updateStSlOpflg(purchaseNotReceiptVo.getPmds055(), 2, "未获取到采购单信息");
                return;
            }
            if (Pmdl005 == 1) {
                purchaseNotReceiptVo.setPmdsdocno(Constant.PMDSDOCNO_3401);
            } else if (Pmdl005 == 3) {
                purchaseNotReceiptVo.setPmdsdocno(Constant.PMDSDOCNO_3402);
            } else {
                purchaseNotReceiptVo.setPmds011(2);
                purchaseNotReceiptVo.setPmdsdocno(Constant.PMDSDOCNO_3410);
            }

            //分批项次信息
            List<ProcurementDetailsVo> procurementDetailsVos = wmsPurchaseMapper.getProcurementDetailsVo(purchaseOrderNos, Pmdl005);
            //没有数据时不会写
            String join = StringUtils.join(purchaseOrderNos, ",");
            if (CollUtil.isEmpty(procurementDetailsVos)) {
                //更新相应表状态为已下发
                wmsPurchaseNewMapper.updateStSlOpflg(purchaseNotReceiptVo.getPmds055(), 2, "对应采购采购单：" + join + "可回写数量不足，该单未回写!");
                return;
            } else {
                //由于可能同一个料分两次收货故要根据料号分组进行计算可回写数量
                Map<String, List<PurchaseNotReceiptListVo>> listMap = purchaseGetListNew.stream().collect(Collectors.groupingBy(PurchaseNotReceiptListVo::getPmdt006));
                for (Map.Entry<String, List<PurchaseNotReceiptListVo>> listEntry : listMap.entrySet()) {
                    String mcode = listEntry.getKey();
                    List<PurchaseNotReceiptListVo> purchaseNotReceiptListVos = listMap.get(listEntry.getKey());
                    //本次料号回填总量
                    BigDecimal returnQty = purchaseNotReceiptListVos.stream().map(PurchaseNotReceiptListVo::getPmdt020).reduce(BigDecimal.ZERO, BigDecimal::add);
                    //采购可收货总数
                    BigDecimal reduce = procurementDetailsVos.stream().filter(item -> item.getPmdn001().equals(mcode)).map(ProcurementDetailsVo::getPmdn007).reduce(BigDecimal.ZERO, BigDecimal::add);
                    //erp已收获数量
                    BigDecimal backQty = procurementDetailsVos.stream().filter(item -> item.getPmdn001().equals(mcode)).map(ProcurementDetailsVo::getReturnQty).reduce(BigDecimal.ZERO, BigDecimal::add);
                    //验退数量
                    BigDecimal pmdt006 = procurementDetailsVos.stream().filter(item -> item.getPmdn001().equals(mcode)).map(ProcurementDetailsVo::getPmdo016).reduce(BigDecimal.ZERO, BigDecimal::add);
                    reduce = reduce.add(pmdt006);
                    if (returnQty.compareTo(reduce.subtract(backQty)) > 0) {
                        //更新相应表状态为已下发
                        wmsPurchaseNewMapper.updateStSlOpflg(purchaseNotReceiptVo.getPmds055(), 2, "料号:" + mcode + "对应采购采购单：" + join + "可回写数量不足，该单未回写!");
                        return;
                    }
                }
            }
            //2024-08-01 新逻辑，新数据默认按照送货单行的采购项次进行抵扣  旧数据按照采购单进行抵扣  待测试
            List<PurchaseNotReceiptListVo> reqList = new ArrayList<>();
            //委外采购情况直接回写不需要计算项次 回写料号为1和6的数据也不需要计算项次
            Integer checkIsWw = wmsPurchaseNewMapper.checkIsWw(purchaseNotReceiptVo.getPmds055());
            if (purchaseNotReceiptVo.getPmds011() == 2 || checkIsWw > 0) {
                for (PurchaseNotReceiptListVo receiptListVo : purchaseGetListNew) {
                    //填充分批序信息
                    receiptListVo.setPmdt004(1);
                    reqList.add(receiptListVo);
                }
            } else {
                //查询erp历史数据
                List<WmsErpSlHistoryData> wmsErpSlHistoryDataList = wmsPurchaseNewMapper.getWmsErpSlHistoryData(purchaseOrderNos);
                for (PurchaseNotReceiptListVo purchaseNotReceiptListVo : purchaseGetListNew) {
                    //采购单号
                    String pmdt001 = purchaseNotReceiptListVo.getPmdt001();
                    //项次
                    Integer pmdt002 = purchaseNotReceiptListVo.getPmdt002();
                    //料号
                    String pmdt006 = purchaseNotReceiptListVo.getPmdt006();
                    //是否历史数据 如果是则按采购单进行计算 料号采购单号是否在erp历史数据中
                    List<ProcurementDetailsVo> procurementDetailsVoList;
                    boolean isHistory = false;
                    if (CollUtil.isNotEmpty(wmsErpSlHistoryDataList)) {
                        //采购单号与料号判定为历史数据
                        List<WmsErpSlHistoryData> collect = wmsErpSlHistoryDataList.stream().filter(item -> item.getMcode().equals(pmdt006) && item.getPmdldocno().equals(pmdt001)).collect(Collectors.toList());
                        if (CollUtil.isNotEmpty(collect)) {
                            isHistory = true;
                        }
                    }
                    if (isHistory) {
                        //旧数据使用老的计算方式 需要考虑采购单与料号相同的问题同一送货单不同行号问题
                        procurementDetailsVoList = wmsPurchaseNewMapper.getProcurementDetailsVoListHistory(pmdt001, pmdt006);
                    } else {
                        //新数据 直接按照项次抵扣 分排序随机分配
                        procurementDetailsVoList = wmsPurchaseNewMapper.getProcurementDetailsVoList(pmdt001, pmdt002);
                    }
                    if (CollUtil.isEmpty(procurementDetailsVoList)) {
                        //更新相应表状态为已下发
                        wmsPurchaseNewMapper.updateStSlOpflg(purchaseNotReceiptVo.getPmds055(), 2, "料号:" + pmdt006 + "对应采购采购单：" + pmdt001 + "可回写数量不足，该单未回写!");
                        return;
                    }
                    //计算序号并添加到回写数据列表中
                    computeSequenceNumber(procurementDetailsVoList, purchaseNotReceiptListVo, reqList, isHistory);
                }
            }
//            Map<String, List<ProcurementDetailsVo>> collect = procurementDetailsVos.stream().collect(Collectors.groupingBy(ProcurementDetailsVo::getPmdldocno));
//            for (PurchaseNotReceiptListVo purchaseNotReceiptListVo : purchaseGetListNew) {
//                //本次回写数量
//                BigDecimal pmdt020 = purchaseNotReceiptListVo.getPmdt020();
//                //原单的项次在项次中
//                List<ProcurementDetailsVo> collectList = collect.get(purchaseNotReceiptListVo.getPmdt001());
//                for (ProcurementDetailsVo procurementDetailsVo : collectList) {
//                    if (!purchaseNotReceiptListVo.getPmdt006().equals(procurementDetailsVo.getPmdn001())) {
//                        continue;
//                    }
//                    BigDecimal pmdn007 = procurementDetailsVo.getPmdn007();
//                    BigDecimal pmdo016 = procurementDetailsVo.getPmdo016();
//                    BigDecimal returnQty = procurementDetailsVo.getReturnQty();
//                    //本项次可回写数量
//                    BigDecimal subtract = pmdn007.add(pmdo016).subtract(returnQty);
//                    if (subtract.compareTo(BigDecimal.ZERO) == 0) {
//                        continue;
//                    }
//                    PurchaseNotReceiptListVo purchaseNotReceiptListVoCopy = BeanUtil.copyProperties(purchaseNotReceiptListVo, PurchaseNotReceiptListVo.class);
//                    purchaseNotReceiptListVoCopy.setPmdt002(procurementDetailsVo.getPmdnseq());
//                    purchaseNotReceiptListVoCopy.setPmdt003(procurementDetailsVo.getPmdoseq1());
//                    purchaseNotReceiptListVoCopy.setPmdt004(procurementDetailsVo.getPmdoseq2());
//                    if (subtract.compareTo(pmdt020) > 0) {
//                        procurementDetailsVo.setReturnQty(returnQty.add(pmdt020));
//                        purchaseNotReceiptListVoCopy.setPmdt020(pmdt020);
//                        reqList.add(purchaseNotReceiptListVoCopy);
//                        //项次相同时
//                        break;
//                    } else {
//                        purchaseNotReceiptListVoCopy.setPmdt020(subtract);
//                        procurementDetailsVo.setReturnQty(returnQty.add(subtract));
//                        pmdt020 = pmdt020.subtract(subtract);
//                        reqList.add(purchaseNotReceiptListVoCopy);
//                    }
//                    if (pmdt020.compareTo(BigDecimal.ZERO) == 0) {
//                        break;
//                    }
//                }
//            }

            if (CollUtil.isEmpty(reqList)) {
                wmsPurchaseNewMapper.updateStSlOpflg(purchaseNotReceiptVo.getPmds055(), 2, "项次计算失败,请联系开发人员");
                return;
            }
            //获取回写json
            wmsPurchaseNewMapper.updateStSlOpflg(purchaseNotReceiptVo.getPmds055(), 3, "erp待返回");
            String resMessage = soapXmlUtil.getSoapXml("PurchaseGet", "pmds_t", "pmdt_t", purchaseNotReceiptVo, reqList);
            log.info("收货回写:{}", resMessage);
            //发送soap消息，并解析结果
            String result;
            try {
                result = soapXmlUtil.sendSoapMessageNew(resMessage, erpConfig.getUrl());
            } catch (Exception e) {
                result = soapXmlUtil.sendSoapMessageNew(resMessage, erpConfig.URL2);
            }
            //调用等待
            if (purchaseGetListNew.size() >= 80) {
                Thread.sleep(80 * 1000);
            } else if (purchaseGetListNew.size() >= 50) {
                Thread.sleep(60 * 1000);
            } else if (purchaseGetListNew.size() >= 30) {
                Thread.sleep(30 * 1000);
            } else if (purchaseGetListNew.size() >= 10) {
                Thread.sleep(5 * 1000);
            }
            log.info("soap接口采购收货(新)回调->{}", result);
            XmlResp xmlResp = soapXmlUtil.analysisXml(result);
            //成功
            if (xmlResp.getCode().equals("0")) {
                wmsPurchaseNewMapper.updateStSlOpflg(purchaseNotReceiptVo.getPmds055(), 1, xmlResp.getData().get("pmdsdocno"));
                //因为每次会写都会重新获取，考虑到性能，故这一步注释更新采购单数据
//                for (String orderNo : purchaseOrderNos) {
//                    wmsPurchaseNewMapper.updatePurchaseReceiptDetails(orderNo);
//                }
                //更新回写单据
                poMpsinfoMapper.syncPurchaseReceiptDetails();
                //生成检验单据
                wmsPurchaseNewMapper.wmsQmsCheckSlno(purchaseNotReceiptVo.getPmds055());
            } else {
                //失败
                wmsPurchaseNewMapper.updateStSlOpflg(purchaseNotReceiptVo.getPmds055(), 2, xmlResp.getMessage());
            }
//            if (ObjectUtil.isNotEmpty(lock) && lock.isHeldByCurrentThread()) {
//                lock.unlock();
//            }
        } catch (Exception e) {
            wmsPurchaseNewMapper.updateStSlOpflg(purchaseNotReceiptVo.getPmds055(), 2, "非常见的数据处理问题，请联系开发人员处理");
            e.printStackTrace();
        }
//        finally {
//            log.error("finally释放锁{}", this.getClass().getName());
//            if (ObjectUtil.isNotEmpty(lock) && lock.isHeldByCurrentThread()) {
//                lock.unlock();
//            }
//        }
    }

    private void computeSequenceNumber(List<ProcurementDetailsVo> procurementDetailsVoList, PurchaseNotReceiptListVo purchaseNotReceiptListVo, List<PurchaseNotReceiptListVo> reqList, boolean isHistory) {
        BigDecimal pmdt020 = purchaseNotReceiptListVo.getPmdt020();
        for (ProcurementDetailsVo procurementDetailsVo : procurementDetailsVoList) {
            BigDecimal pmdn007 = procurementDetailsVo.getPmdn007();
            BigDecimal pmdo016 = procurementDetailsVo.getPmdo016();
            BigDecimal returnQty = procurementDetailsVo.getReturnQty();
            //本项次可回写数量 = 采购数量 + 验退数量 - 已回写数量
            BigDecimal subtract = pmdn007.add(pmdo016).subtract(returnQty);
            //历史数据时需要减去回写列表中的数据
            if (isHistory && CollUtil.isNotEmpty(reqList)) {
                BigDecimal reqListNum = BigDecimal.ZERO;
                for (PurchaseNotReceiptListVo receiptListVo : reqList) {
                    //根据采购单号 项次 项序 分批序 加入已经计算的回写数量
                    if (receiptListVo.getPmdt002().equals(procurementDetailsVo.getPmdnseq()) && procurementDetailsVo.getPmdldocno().equals(receiptListVo.getPmdt001())
                            && receiptListVo.getPmdt003().equals(procurementDetailsVo.getPmdoseq1()) && receiptListVo.getPmdt004().equals(procurementDetailsVo.getPmdoseq2())) {
                        reqListNum = reqListNum.add(receiptListVo.getPmdt020());
                    }
                }
                subtract = subtract.subtract(reqListNum);
            }
            if (subtract.compareTo(BigDecimal.ZERO) == 0) {
                continue;
            }
            PurchaseNotReceiptListVo purchaseNotReceiptListVoCopy = BeanUtil.copyProperties(purchaseNotReceiptListVo, PurchaseNotReceiptListVo.class);
            //项次
            purchaseNotReceiptListVoCopy.setPmdt002(procurementDetailsVo.getPmdnseq());
            //项序
            purchaseNotReceiptListVoCopy.setPmdt003(procurementDetailsVo.getPmdoseq1());
            //分批序
            purchaseNotReceiptListVoCopy.setPmdt004(procurementDetailsVo.getPmdoseq2());
            if (subtract.compareTo(pmdt020) > 0) {
                purchaseNotReceiptListVoCopy.setPmdt020(pmdt020);
                reqList.add(purchaseNotReceiptListVoCopy);
                //项次相同时
                break;
            } else {
                purchaseNotReceiptListVoCopy.setPmdt020(subtract);
                pmdt020 = pmdt020.subtract(subtract);
                reqList.add(purchaseNotReceiptListVoCopy);
            }
            if (pmdt020.compareTo(BigDecimal.ZERO) == 0) {
                break;
            }
        }
    }

}
